package itpenguin.review;

import itpenguin.common.PMFactory;
import itpenguin.review.entities.Item;
import itpenguin.review.util.ReviewUtil;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.TimeZone;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.stream.XMLStreamException;

import org.apache.commons.codec.binary.Base64;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;

public class UpdateServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		
		String itemId = ReviewUtil.getItemId(req);
		if (("cache").equals(itemId)) {
			
			CacheFilter.clearCache(getServletConfig().getServletContext());
			return;
		}
		
		PersistenceManager pm = PMFactory.getInstance().getPersistenceManager();
		Item item = null;
		try {
			pm = PMFactory.getInstance().getPersistenceManager();
			Key k = KeyFactory.createKey(Item.class.getSimpleName(), itemId); 
			
			try {
				item = pm.getObjectById(Item.class, k);
				item = pm.detachCopy(item);
			} catch (NullPointerException e) {
			} catch (JDOObjectNotFoundException e) {
			}
		} finally {
			pm.close();
		}

		if (item == null)
			item = new Item(itemId);
		
		try {
			item.updateItemInfo();
		} catch (XMLStreamException e) {
			throw new ServletException(e);
		}
		
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		ObjectOutputStream oo = new ObjectOutputStream(bos);
		oo.writeObject(item);
		String encodedItem = new String(Base64.encodeBase64(bos.toByteArray()), "UTF-8");
		
		if (item.getReviewDate() == null)
			item.setReviewDate(new Date());
		
		moveToImputForm(req, resp, item, encodedItem);
		
	}

	private void moveToImputForm(HttpServletRequest req,
			HttpServletResponse resp, Item item, String encodedItem) throws ServletException, IOException {
		
		req.setAttribute("item", item);
		req.setAttribute("encodedItem", encodedItem);
		
		RequestDispatcher rd = req.getRequestDispatcher("/WEB-INF/pages/update.jsp");
		rd.forward(req, resp);
	}
	
	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		
		String encodedItem = req.getParameter("encodedItem");
		byte[] decode = Base64.decodeBase64(encodedItem.getBytes("UTF-8"));

		ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(decode));
		Item item = null;
		try {
			item = (Item) ois.readObject();
		} catch (ClassNotFoundException e) {
			throw new ServletException(e);
		}
		item.setReviewTitle(req.getParameter("reviewTitle"));
		item.setReview(req.getParameter("review"));
		
		try {
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm");
			sdf.setTimeZone(TimeZone.getTimeZone("JST"));
			item.setReviewDate(sdf.parse(req.getParameter("reviewDate")));
		} catch (ParseException e) {
			req.setAttribute("message", "Date format error.");
			moveToImputForm(req, resp, item, encodedItem);
		}
		
		try {
			short score = Short.parseShort(req.getParameter("score"));
			item.setScore(score);
			if (score > 100 || score < 0){
				req.setAttribute("message", "Score renge error.");
				moveToImputForm(req, resp, item, encodedItem);
			}
		} catch (NumberFormatException e) {
			req.setAttribute("message", "Score format error.");
			moveToImputForm(req, resp, item, encodedItem);
		}
		
		String newAsin = req.getParameter("asin");
		if (! item.getAsin().equals(newAsin))
		{
			try {
				item.setAsin(newAsin);
				item.updateItemInfo();
			} catch (XMLStreamException e) {
				req.setAttribute("message", "ASIN is invalid.");
				moveToImputForm(req, resp, item, encodedItem);
			}
		}
		
		String relatedAsinsStr = req.getParameter("relatedAsins");
		List<String> relatedAsins = item.getRelatedAsins();
		relatedAsins.clear();
		if (relatedAsinsStr != null && relatedAsinsStr.trim().length() > 0) {
			relatedAsins.addAll(Arrays.asList(relatedAsinsStr.split("[, 　]+")));
		}
	
		item.setLastModified(new Date());
		
		PersistenceManager pm = PMFactory.getInstance().getPersistenceManager();
		pm.makePersistent(item);
		pm.close();
		
		// Cache clear
		CacheFilter.clearCache(getServletConfig().getServletContext());
		
		// Move to review page
		resp.sendRedirect("/review/" + item.getItemId());
		
	}
	
}
